import re
import json
from typing import List, Dict, Optional
from langchain_openai import ChatOpenAI
from langchain.schema import HumanMessage


class NLPTool:
    def __init__(self, llm: Optional[ChatOpenAI] = None):
        self.llm = llm

    def analyze_intent(self, query: str) -> Dict:
        """分析用户查询意图"""
        if not self.llm:
            return {
                "query_type": "keyword_search",
                "parameters": {"keyword": query}
            }

        try:
            # 首先检查是否是询价查询
            price_query_patterns = [
                r"(.+)多少钱",
                r"(.+)什么价",
                r"(.+)价格",
                r"(.+)卖多少"
            ]

            for pattern in price_query_patterns:
                match = re.match(pattern, query)
                if match:
                    product_name = match.group(1).strip()
                    return {
                        "query_type": "category_search",
                        "parameters": {
                            "category": product_name
                        },
                        "explanation": f"用户询问{product_name}的价格"
                    }

            # 构建提示词
            prompt = f"""请分析以下用户查询，并返回结构化的查询意图。
用户查询: "{query}"

请考虑以下几个方面:
1. 用户是否在寻找特定类别的商品？(如手机、电脑、相机、厨具、食材等)
2. 用户是否提到了价格范围或价格要求？
   - 具体价格范围（如：100-200元）
   - 模糊价格描述（如：便宜的、实惠的、高端的）
3. 用户是否有其他特定需求？(如品牌、功能特点、用途等)

对于价格相关的查询，请按照以下规则处理：
- 如果提到"便宜"、"实惠"、"便宜点的"等词，设置价格范围为0-50元
- 如果提到"中等"、"适中"等词，设置价格范围为50-200元
- 如果提到"高端"、"奢侈"等词，设置价格范围为200元以上
- 如果询问具体商品价格，使用category_search类型并返回该商品类别

请以JSON格式返回分析结果，格式如下:
{{
    "query_type": "price_search|category_search|keyword_search",
    "parameters": {{
        // 对于price_search:
        "min_price": 数字,
        "max_price": 数字
        // 对于category_search:
        "category": "类别名称"
        // 对于keyword_search:
        "keyword": "搜索关键词"
    }},
    "explanation": "解释为什么选择这种查询类型"
}}

注意：
1. 价格必须是具体的数字
2. 对于price_search类型，min_price和max_price都必须有值
3. 返回的必须是有效的JSON格式，不要包含任何其他文字或标记"""

            # 调用LLM分析意图
            response = self.llm.invoke(
                [HumanMessage(content=prompt)]
            )

            try:
                # 清理响应内容
                content = response.content
                # 移除可能的markdown标记和注释
                if "```json" in content:
                    content = content.split("```json")[1].split("```")[0].strip()
                elif "```" in content:
                    content = content.split("```")[1].strip()

                # 移除注释行
                content_lines = [line for line in content.split('\n') if not line.strip().startswith('//')]
                content = '\n'.join(content_lines)

                # 解析JSON
                result = json.loads(content)
                print(f"LLM意图分析结果: {result}")

                # 处理价格相关的特殊情况
                if result["query_type"] == "price_search":
                    # 确保价格值有效
                    if result["parameters"].get("min_price") is None or result["parameters"].get("max_price") is None:
                        # 检查是否包含价格相关的关键词
                        if any(word in query for word in ["便宜", "实惠", "便宜点"]):
                            result["parameters"]["min_price"] = 0
                            result["parameters"]["max_price"] = 50
                        elif any(word in query for word in ["中等", "适中"]):
                            result["parameters"]["min_price"] = 50
                            result["parameters"]["max_price"] = 200
                        elif any(word in query for word in ["高端", "奢侈"]):
                            result["parameters"]["min_price"] = 200
                            result["parameters"]["max_price"] = 10000
                        else:
                            # 如果没有明确的价格信息，转为关键词搜索
                            result = {
                                "query_type": "keyword_search",
                                "parameters": {"keyword": query},
                                "explanation": "没有明确的价格信息，使用关键词搜索"
                            }

                # 对于学习做饭的特殊处理
                if "做饭" in query or "烹饪" in query or "厨艺" in query:
                    return {
                        "query_type": "category_search",
                        "parameters": {
                            "category": "厨具"
                        },
                        "explanation": "用户想要学习做饭，推荐厨具和食材"
                    }

                return result

            except json.JSONDecodeError as e:
                print(f"JSON解析错误: {str(e)}, 原始响应: {response.content}")
                return {
                    "query_type": "keyword_search",
                    "parameters": {"keyword": query},
                    "explanation": "解析失败，使用默认搜索"
                }

        except Exception as e:
            print(f"意图分析出错: {str(e)}")
            return {
                "query_type": "keyword_search",
                "parameters": {"keyword": query},
                "explanation": "发生错误，使用默认搜索"
            }

    def generate_recommendation_text(self, products: List[Dict], query: str) -> str:
        """生成商品推荐文案"""
        if not self.llm:
            if not products:
                return "抱歉，没有找到符合条件的商品。请尝试调整搜索条件。"
            return f'根据您的需求"{query}"，为您推荐以下商品：\n\n' + "\n\n".join(
                [f"{i + 1}. {p['name']} - ¥{p['price']}/件" for i, p in enumerate(products[:3])]
            )

        try:
            if not products:
                prompt = f"""用户查询: "{query}"
但是没有找到任何符合条件的商品。

请分析用户的查询意图，生成一个友好的回复。需要：
1. 解释为什么没有找到合适的商品
2. 给出具体的建议，比如调整价格范围、尝试其他类别等
3. 如果是价格相关的查询，建议尝试其他价格区间
4. 保持语气友好，给出建设性的建议"""

                response = self.llm.invoke([HumanMessage(content=prompt)])
                return response.content

            # 检查是否是询价查询
            is_price_query = any(pattern in query for pattern in ["多少钱", "什么价", "价格", "卖多少"])

            # 构建商品信息，添加量词处理
            product_info = []
            category_prices = {}  # 用于统计每个类别的价格范围

            # 定义类别对应的量词
            category_units = {
                "水果": "元/斤",
                "蔬菜": "元/斤",
                "肉类": "元/斤",
                "海鲜": "元/斤",
                "乳制品": "元/盒",
                "饮品": "元/瓶",
                "零食": "元/包",
                "家居用品": "元/件",
                "电子产品": "元/台",
                "运动用品": "元/个",
                "烘焙": "元/个"
            }

            for i, product in enumerate(products[:5], 1):
                category = product.get('category_name', '')
                unit = category_units.get(category, "元/件")  # 如果没有特定量词，默认使用"件"

                # 特殊处理某些商品的量词
                if "水" in product['name'] or "饮料" in product['name'] or "酒" in product['name']:
                    unit = "元/瓶"
                elif "纸" in product['name']:
                    unit = "元/包"
                elif any(word in product['name'] for word in ["米", "面", "粮"]):
                    unit = "元/kg"

                info = [f"{i}. {product['name']}"]
                info.append(f"   价格: ¥{product['price']}{unit}")
                if 'brand' in product:
                    info.append(f"   品牌: {product['brand']}")
                if 'product_description' in product:
                    info.append(f"   特点: {product['product_description'][:100]}...")
                if category:
                    info.append(f"   类别: {category}")
                    # 统计类别价格
                    if category not in category_prices:
                        category_prices[category] = []
                    category_prices[category].append(product['price'])
                if 'total_sales' in product:
                    info.append(f"   销量: {product['total_sales']}件")
                product_info.append("\n".join(info))

            # 构建推荐提示
            if is_price_query:
                # 计算每个类别的价格范围
                price_ranges = {}
                for category, prices in category_prices.items():
                    if prices:
                        unit = category_units.get(category, "元/件")
                        price_ranges[category] = {
                            'min': min(prices),
                            'max': max(prices),
                            'avg': sum(prices) / len(prices),
                            'unit': unit
                        }

                price_info = []
                for category, range_info in price_ranges.items():
                    if range_info['min'] == range_info['max']:
                        price_info.append(f"{category}的价格为 ¥{range_info['min']}{range_info['unit']}")
                    else:
                        price_info.append(
                            f"{category}的价格范围在 ¥{range_info['min']} 到 ¥{range_info['max']}{range_info['unit']} 之间，平均价格 ¥{range_info['avg']:.2f}{range_info['unit']}")

                prompt = f"""用户查询: "{query}"

找到的商品价格信息:
{chr(10).join(price_info)}

详细商品信息:
{chr(10).join(product_info)}

请生成一个详细的价格说明和推荐文案。要求：
1. 首先说明价格区间和平均价格，注意使用正确的量词（斤、kg、个、包、瓶等）
2. 解释不同价位商品的特点和优势
3. 对于每个价位段：
   - 说明该价位商品的特色
   - 适合的购买场景
   - 性价比分析
4. 给出购买建议：
   - 如何根据预算选择
   - 最具性价比的选择
   - 适合不同需求的选择
5. 语言要客观专业，重点突出价格信息和计量单位

请直接生成推荐文案，不要包含模板标记。"""
            else:
                prompt = f"""用户查询: "{query}"

找到的商品信息:
{chr(10).join(product_info)}

请根据用户的查询意图和找到的商品信息，生成一个个性化的推荐文案。要求：
1. 首先分析用户的需求（比如是否关注价格、品质等）
2. 解释为什么推荐这些商品
3. 对于每个商品：
   - 说明其价格优势或性价比，使用合适的计量单位（斤、kg、个、包、瓶等）
   - 突出其核心特色和优点
   - 说明适用场景
4. 如果有多个商品：
   - 进行价格和特点的对比分析
   - 针对不同预算给出建议
5. 给出明确的购买建议，包括：
   - 哪些商品最适合用户需求
   - 性价比最高的选择
   - 如何根据预算做选择
6. 语言要自然流畅，富有感染力

请直接生成推荐文案，不要包含模板标记。"""

            response = self.llm.invoke([HumanMessage(content=prompt)])
            return response.content

        except Exception as e:
            print(f"生成推荐文案出错: {str(e)}")
            return "抱歉，生成推荐文案时出现错误。"
